home *** CD-ROM | disk | FTP | other *** search
-
- * EXAMPLE OF USE!
-
-
- move.w #$4000,$dff09a
-
- jsr INIT_DISK
-
- move.l #loadspace,a5 ;address of load
- move.l #filename,a6 ;address of filename
- moveq #0,d7 ;load mode set
-
- jsr LOAD_FILE
-
- tst.w d7 ;check for failure
- beq.s loadok
-
- move.w #$7fff,d0 ;red screen = error
- erlp move.w #$f00,$dff180
- dbf d0,erlp
-
- loadok jsr MOTOR_OFF
- move.w #$c000,$dff09a
- rts
-
- filename dc.b "df0:testfile",$00
-
- even
-
- loadspace dcb.l $8000,$00
-
- *****************************************************************************
-
- * System Independant Multi-Disk AmigaDos File Loader V1.1- 26/4/94 *
- *----------------------------------------------------------------------*
-
- * By PHIL RUSTON AKA:PHIL!94/LSD *
-
- * You MUST Call "INIT_DISK" before loading for the 1st time ever!
-
- * To LOAD A FILE Set:-
-
- * A6 = Address of 0 ended filename (MUST include a path, subdirs allowed.)
- * A5 = Load address.
- * D7 = Mode: 0 = Load, 1 = Search and Return file length in A5 only.
-
- * Then call: "LOAD_FILE" - All registers preserved except A5 and D7.
-
- * A5 returns as last byte address of file + 1
- * D7 returns as 0 if load OK. Or one of the following errors:
-
- * 01 = No speed signal from motor (disk removed whilst loading?)
- * 02 = No DMA transfer time out (not a dos disk / '' '')
- * 03 = Disk removed from drive (disk removed whilst loading)
- * 04 = Can't find that disk block (disk corrupt)
- * 05 = Wrong track marker ID ('')
- * 06 = Checksum error on disk block ('')
- * 07 = Block requested out of range ('')
- * 08 = Not a file (Its a directory!)
- * 09 = File not found
- * 0a = That drive is not connected. (Direct drive access failed)
- * 0b = There is no disk in that drive. ( '' '' )
- * 0c = Disk requester. (Disk specified not in any drive)
- * 0d = No path given (I require disk or drive name!)
-
- * Dont forget to call "MOTOR_OFF" when finished loading for a while!!
- * But NOT between each in batch of files!
-
- * See DOCS for more info - If you use this code please credit me and
- * consider sendimg me a token of your appreciation.. Cash welcome!
-
- *******************************************************************************
-
- section loadcode,code
-
- **************
- * Initialize *
- **************
-
- INIT_DISK movem.l a0-a6/d0-d7,-(a7)
- move.l #$dff000,a0
- move.l #$bfd000,a1
- move.l #Variables,a2
- clr.l attempts(a2)
- clr.l tracksides(a2)
- clr.l track_in(a2)
- clr.l load_address(a2)
- bsr Motor_off
-
- bset #3,drives_avail(a2) ;df0: assumed always available
- moveq #4,d1
- ID_drives move.b #$7f,$100(a1) ;what externals are connected?
- bclr d1,$100(a1)
- move.w #100,d7
- bsr cia_wait
- move.b #$ff,$100(a1)
- bclr d1,$100(a1)
- moveq #$1f,d7
- moveq #0,d0
- df1idloop lsl.l #1,d0
- bclr d1,$100(a1)
- btst #5,$1001(a1)
- beq.s nxtbit
- ori.w #1,d0
- nxtbit bset d1,$100(a1)
- dbf d7,df1idloop
- not.l d0
- cmpi.l #-1,d0
- bne.s no_drive
- bset d1,drives_avail(a2)
-
- no_drive addq.w #1,d1
- cmpi.w #7,d1
- bne.s ID_drives
- bsr motor_off
-
- moveq #0,d0 ;now identify any disks present.
- moveq #3,d1
- id_dsk_lp btst d1,drives_avail(a2)
- beq.s no_drv
- move.b d0,use_drive(a2)
- move.b #$ff,$100(a1)
- bclr d1,$100(a1)
- bsr stepin
- bsr initialize_drive
- btst #2,$1001(a1)
- beq.s no_drv
- move.b #1,start_motor(a2)
- bsr identify_disk
- no_drv bsr motor_off
- addq.w #1,d1
- addq.w #1,d0
- cmpi.w #4,d0
- bne.s id_dsk_lp
- movem.l (a7)+,a0-a6/d0-d7
- rts
-
- *****************************************************************************
-
- ***************
- * File Loader *
- ***************
-
- LOAD_FILE movem.l d0-d6/a0-a4/a6,-(a7)
- move.l #$bfd000,a1
- move.l #Variables,a2
- move.l a5,load_address(a2)
- move.b d7,mode(a2)
-
- move.l a6,a0 ;analyse file name for path.
- moveq #0,d0
- find_path tst.b (a0)
- beq no_path
- cmpi.b #":",(a0)+
- beq.s found_path
- addq.w #1,d0
- cmpi.w #32,d0
- bne.s find_path
- bra no_path
- found_path
- moveq #0,d2 ;direct drive access (df0: etc?)
- move.l #direct_names,a0
- lk_direct moveq #4,d1
- bsr compare_text
- tst.w d7
- bne.s direct_path
- addq.w #4,a0
- addq.w #1,d2
- cmpi.w #4,d2
- bne.s lk_direct
- bra not_direct
-
- direct_path
-
- move.l d2,d1 ;direct drive access requested
- addq #3,d1 ;but is that drive available?
- btst d1,drives_avail(a2)
- bne.s drv_avl
- move.b #$0a,error(a2) ;no - error $0a
- bra load_end
- drv_avl
- cmp.b use_drive(a2),d2 ;same drive used previously?
- beq Go_load
- bsr motor_off
- move.b d2,use_drive(a2) ;select it if not
- move.b #$ff,$100(a1)
- bclr d1,$100(a1)
- bsr wait1msec
-
- same_drv1 btst #2,$1001(a1) ;disk in?
- beq Dchngd1
- move.b #1,start_motor(a2)
- bra Go_load
-
- Dchngd1 bsr test_step
- btst #2,$1001(a1) ;disk in now?
- bne.s Dnowin
- move.b #$0b,error(a2) ;no disk in that drive-error $0b
- bra load_end
-
- Dnowin move.b #1,start_motor(a2)
- bsr initialize_drive
- bsr identify_disk
- bra Go_load
-
- not_direct
-
- lea disk_names(a2),a0 ;look through currently inserted
- addq.w #1,a0
- moveq #0,d2 ;disks for that diskname.
-
- lk_disk move.w d0,d1
- cmp.b -$1(a0),d0 ;compare diskname length
- bne.s not_in2
- bsr compare_text
- tst.w d7
- bne.s got_path
-
- not_in2 add.w #$20,a0 ;look in next drives name-store
- addq.w #1,d2
- cmpi.w #4,d2
- bne.s lk_disk
- bra not_inserted
-
- got_path cmp.b use_drive(a2),d2 ;same drive used previously?
- beq Go_load
- bsr motor_off
- move.b d2,use_drive(a2) ;select it if not
- move.b #$ff,$100(a1)
- move.l d2,d1
- addq.w #3,d1
- bclr d1,$100(a1)
- bsr wait1msec
- btst #2,$1001(a1) ;disk in?
- beq Doutnow
- move.b #1,start_motor(a2)
- bra Go_load
-
- Doutnow subq.w #1,a0 ;ejected - clear stored name
- moveq #$1f,d7
- clr_name clr.b (a0)+
- dbf d7,clr_name
-
- not_inserted
-
- moveq #0,d2 ;see if any disks have been
- tdrv_loop move.w d2,d1 ;replaced, and identify any new
- add.w #3,d1 ;disks. If any match req then
- bsr motor_off ;load.
- btst d1,drives_avail(a2)
- beq.s nxt_drv
- move.b #$ff,$100(a1)
- bclr d1,$100(a1)
- bsr wait1msec
- btst #2,$1001(a1)
- bne.s nxt_drv
- move.b d2,use_drive(a2)
- bsr test_step
- btst #2,$1001(a1)
- bne.s dsk_now_in
- lea disk_names(a2),a0 ;still no disk so wipe diskname
- move.w d2,d1
- lsl.w #5,d1
- add.w d1,a0
- moveq #$1f,d1
- wipe_dn clr.b (a0)+
- dbf d1,wipe_dn
- bra.s nxt_drv
- dsk_now_in
- move.b #1,start_motor(a2)
- bsr initialize_drive
- bsr identify_disk
- lea disk_names(a2),a0 ;correct diskname
- move.w d2,d1
- lsl.w #5,d1
- add.w d1,a0
- cmp.b (a0),d0 ;compare diskname length
- bne.s nxt_drv
- move.w d0,d1
- addq.w #1,a0
- bsr compare_text
- tst.w d7
- bne Go_load
-
- nxt_drv addq.w #1,d2
- cmpi.w #4,d2
- bne.s tdrv_loop
- move.b #$0c,error(a2) ;disk not in any drive - error $c
- bra Load_end
-
- no_path move.b #$0d,error(a2) ;no path - error $d
- bra Load_end
-
- Go_load lea $01(a6,d0.w),a6 ;bypass path part of filename
- bsr Find_file
-
- Load_end move.b #$ff,track_in(a2)
- tst.b error(a2)
- beq.s no_error
- bsr motor_off
- move.w #1000,d7
- bsr cia_wait
- no_error moveq #0,d7
- move.b error(a2),d7
- movem.l (a7)+,d0-d6/a0-a4/a6
- rts
-
- ****************************************************************************
-
- ********************
- * Shut down drives *
- ********************
-
- MOTOR_OFF movem.l a1/a2/d7,-(a7)
- move.l #$bfd000,a1
- move.l #Variables,a2
- move.b #$ff,$100(a1)
- move.b #$87,$100(a1)
- bsr wait1msec
- move.b #$ff,$100(a1)
- move.b #$ff,use_drive(a2)
- moveq #100,d7
- bsr cia_wait
- movem.l (a7)+,a1/a2/d7
- rts
-
- ****************************************************************************
-
- *********************
- * Get Main Root Dir *
- *********************
-
- Find_file clr.b error(a2)
- move.l #block_buffer,a0 ;get disk's root dir.
- move.w #880,d0
- bsr Get_block
- tst.b error(a2)
- bne file_eror
-
- ******************************
- * Find File's Root Directory *
- ******************************
-
- Find_files_root_dir_loop
-
- move.l a6,a4
- moveq #0,d0
-
- dir_loop move.b (a4),d7 ;find file's root dir
- beq.s root_dir
- cmpi.b #"/",d7 ;and get length of subdir name
- beq.s oblique ;if required.
- addq.w #1,a4
- addq.w #1,d0
- bra dir_loop
-
- oblique move.w d0,d7 ;d0 = dir name length
- move.w d0,d6
- subq.w #1,d7
-
- bsr hash_name ;hash dir name into d0
-
- lsl.w #2,d0
- move.l $18(a0,d0.w),d0 ;header block for this hash
- beq file_not_found
-
- get_dir_header
-
- bsr Get_block
- tst.b error(a2)
- bne file_eror
-
- bsr compare_names
- tst.w d7
- beq.s next_in_hash_chain
- addq.w #1,a4
- move.l a4,a6
- bra find_files_root_dir_loop
-
- next_in_hash_chain
-
- move.l $1f0(a0),d0
- bne get_dir_header
- bra file_not_found
-
- **************************
- * Locate The File Itself *
- **************************
-
- root_dir move.w d0,d7 ;length of file name
- move.w d0,d6
- subq.w #1,d7
-
- bsr hash_name
-
- lsl.w #2,d0
- move.l $18(a0,d0.w),d0 ;header block number for this hash
- beq file_not_found
-
- get_header
-
- bsr Get_block
- tst.b error(a2)
- bne file_eror
-
- bsr compare_names
- tst.w d7
- bne.s correct_file_header
-
- move.l $1f0(a0),d0 ;any more in hash chain?
- bne get_header
- bra file_not_found
-
- correct_file_header
-
- cmpi.l #-3,$1fc(a0) ;make sure its a file header
- beq.s file_header
- move.b #8,error(a2) ;not a file header-error 8
- bra file_eror
-
- file_header
-
- move.l load_address(a2),a5
- move.l $144(a0),d6 ;length of file.
- tst.b mode(a2)
- beq.s transfer
- move.l d6,a5
- rts
- transfer
- subq.l #1,d6
-
- transfer_loop
-
- move.l $10(a0),d0 ;next block location
- beq file_not_found
-
- bsr Get_block
- tst.b error(a2)
- bne file_eror
-
- ****************************************
- * Download data to file's load address *
- ****************************************
-
- lea $18(a0),a3 ;1st data longword in dos_block
- moveq #$79,d7
- make_file subq.l #4,d6
- bmi.s last_bytes
- move.l (a3)+,(a5)+
- dbf d7,make_file
- bra transfer_loop
- last_bytes
- addq.w #4,d6
- lb_loop move.b (a3)+,(a5)+
- dbf d6,lb_loop
- rts
-
- file_not_found
-
- move.b #9,error(a2) ;file not found-error 8
- file_eror rts
-
- *****************************
- * File Load Called Routines *
- *****************************
-
- hash_name move.l a6,a3
- hash_loop moveq #0,d2 ;hash file name at a6
- move.b (a3)+,d2 ;length-1 in d7.
- cmpi.b #$60,d2
- bls.s capital
- cmpi.b #$7a,d2
- bhi.s capital
- subi.b #$20,d2
- capital mulu #13,d0
- add.l d2,d0
- andi.l #$7ff,d0
- dbf d7,hash_loop
- divu #72,d0
- swap d0 ;d0=hash number
- rts
-
- compare_names
-
- moveq #0,d7
- cmp.b $1b0(a0),d6 ;d6=length of name being tested
- bne.s name_fail
- move.w d6,d5
- move.l a6,a3
- lea $1b1(a0),a5
- subq.w #1,d5
- comp_loop move.b (a3)+,d1 ;Case desensitize filename
- move.b (a5)+,d2 ;compare.
- andi.b #$df,d1
- andi.b #$df,d2
- cmp.b d1,d2
- dbne d5,comp_loop
- tst.w d5
- bpl.s name_fail
- moveq #1,d7
- name_fail rts
-
- compare_text
-
- movem.l a0/a6/d2/d3,-(a7) ;Text comparison.
- subq.w #1,d1
- moveq #0,d7 ;d1 = number of chars to compare
- cmp_loop2 move.b (a0)+,d2 ;Strings at A0 and A6
- move.b (a6)+,d3 ;d7: 0 = different, 1 = same.
- andi.b #$df,d2
- andi.b #$df,d3
- cmp.b d2,d3
- bne not_same
- dbf d1,cmp_loop2
- txt_same moveq #1,d7
- not_same movem.l (a7)+,a0/a6/d2/d3
- rts
-
- *****************************************************************************
-
- *********************************
- * Get a disk block into buffer! *
- *********************************
-
- * D0 will equal block number required ($0 - $6df)
-
- Get_block movem.l a0-a6/d0-d7,-(a7)
- move.w #$0504,attempts(a2)
- andi.l #$ffff,d0
- cmpi.w #$6df,d0 ;check range
- bls blk_in_range
- move.b #7,error(a2)
- bra no_reload
-
- blk_in_range
-
- move.l d0,d1
- divu #11,d1 ;what cylinder is that on?
- cmp.b track_in(a2),d1
- beq.s Trksde_in ;that track is already in.
-
- Reload bsr Fetch_trackside ;loads track required
- tst.b error(a2)
- bne No_reload
-
- Trksde_in clr.b error(a2)
- move.l #MFMbuffer,a3
- lea $31fe(a3),a0
- find_sync move.w #$4489,d7
- fs_loop cmp.w (a3)+,d7
- beq found_sync
- cmp.l a0,a3
- bls.s fs_loop
- move.b #4,error(a2) ;couldnt find that sector-error 4
- bra MFM_error
-
- found_sync
-
- cmp.w (a3),d7
- beq.s syncstart
- subq.w #2,a3
-
- syncstart lea $2a(a3),a4 ;Check header checksum.
- bsr decode_lw
- move.l $2(a3),d3
- move.l $6(a3),d4
- andi.l #$55555555,d3
- andi.l #$55555555,d4
- eor.l d4,d3
- cmp.l d3,d5
- bne Not_sector
-
- lea $2(a3),a4 ;Track mark = Head position?
- bsr decode_lw
- move.l d5,d4
- swap d4
- moveq #0,d7
- move.b use_drive(a2),d7
- cmp.b tracksides(a2,d7.w),d4
- beq Track_mark_ok
- move.b #5,error(a2) ;wrong track mark - error 5
- bra MFM_error
-
- Track_mark_ok
-
- lsr.w #8,d5 ;Is this the sector required?
- move.l d1,d7
- swap d7
- cmp.b d5,d7
- beq.s Found_block
-
- Not_sector
-
- add.w #$430,a3 ;loop until find correct sector
- bra find_sync
-
- Found_Block
-
- moveq #0,d2 ;Put converted mfm at dest addr.
- move.l #$55555555,d7
- move.l #block_buffer,a6
- lea $3a(a3),a4
- lea $23a(a3),a5
- moveq #$7f,d3
-
- next_lw move.l (a4)+,d6
- move.l (a5)+,d5
- and.l d7,d6
- and.l d7,d5
- eor.l d6,d2 ;update checksum
- eor.l d5,d2
- add.l d6,d6
- or.l d5,d6
- move.l d6,(a6)+
- dbf d3,next_lw
-
- sub.w #$208,a4
- bsr decode_lw
- cmp.l d5,d2
- beq.s no_reload
- move.b #6,error(a2) ;checksum error - error 6
-
- MFM_error subq.b #1,attempts(a2)
- bne Reload
- bsr initialize_drive
- move.b #5,attempts(a2)
- subq.b #1,attempts+1(a2)
- bne Reload
-
- No_reload movem.l (a7)+,a0-a6/d0-d7
- rts
-
- *****************************************************************************
-
- *********************
- * MFM Track loader! *
- *********************
-
- * D1 will equal trackside 0 - 159
-
- Fetch_trackside
-
- movem.l a0/d0-d3,-(a7)
- move.l #$dff000,a0
- clr.b error(a2)
- tst.b start_motor(a2) ;motor on already?
- beq.s motor_ok
-
- clr.b start_motor(a2)
- move.b #$7f,$100(a1)
- moveq #3,d7
- add.b use_drive(a2),d7
- bclr d7,$100(a1)
- move.w #200,d2 ;wait for correct motor speed.
- wdskrdy moveq #10,d7
- bsr cia_wait
- btst #5,$1001(a1)
- dbeq d2,wdskrdy
- tst.w d2
- bpl.s motor_ok
- move.b #1,error(a2) ;no speed signal - error 1
- btst #2,$1001(a1)
- bne.s disk_ok
- move.b #3,error(a2) ;disk removed - error 3
- disk_ok bra trackload_end
-
- motor_ok move.w d1,d3
- lsr.b #1,d3 ;select disk side to load from.
- bcc.s head1
- bclr #2,$100(a1)
- bra.s checkhead
- head1 bset #2,$100(a1)
-
- checkhead moveq #0,d7
- move.b use_drive(a2),d7
- move.b tracksides(a2,d7.w),d2 ;ensure head is over correct
- lsr.b #1,d2 ;track
- cmp.b d2,d3
- beq.s headok
- bls.s seekout
- bsr stepin
- bra.s checkhead
- seekout bsr stepout
- bra.s checkhead
-
- headok moveq #0,d7
- move.b use_drive(a2),d7
- move.b d1,tracksides(a2,d7.w)
- move.w #$2,$9c(a0) ;clear disk block irq
- moveq #18,d7 ;settle wait.
- bsr cia_wait
-
- move.l #mfmbuffer,$20(a0)
- move.w #$4000,$24(a0)
- move.w #$8010,$96(a0) ;enable dma
- move.w #$6800,$9e(a0)
- move.w #$9500,$9e(a0)
- move.w #$4489,$7e(a0) ;sync
- move.w #$9900,$24(a0)
- move.w #$9900,$24(a0)
-
- move.w #200,d2
- waitdirq moveq #10,d7
- bsr cia_wait
- btst #1,$1f(a0)
- dbne d2,waitdirq
- tst.w d2
- bpl.s read_ok
- move.b #2,error(a2) ;No DMA finish-Time Out-error 2
-
- read_ok move.b d1,track_in(a2)
- move.w #$4000,$24(a0)
- move.w #$10,$96(a0) ;disable dma
-
- Trackload_end
-
- movem.l (a7)+,a0/d0-d3
- rts
-
- *******************************************************************************
-
- ******************************
- * MFM + disk h/ware routines *
- ******************************
-
- decode_lw move.l #$55555555,d7 ;decode two consec mfm longwords
- move.l (a4),d5 ;into d5
- move.l $4(a4),d4
- and.l d7,d5
- and.l d7,d4
- add.l d5,d5
- or.l d4,d5
- rts
-
- stepout moveq #0,d7
- move.b use_drive(a2),d7
- subq.b #2,tracksides(a2,d7.w)
- bset #1,$100(a1)
- bra.s step
-
- stepin moveq #0,d7
- move.b use_drive(a2),d7
- addq.b #2,tracksides(a2,d7.w)
- bclr #1,$100(a1)
- step bsr.s shortwait
- bclr #0,$100(a1)
- bsr.s shortwait
- bset #0,$100(a1)
- moveq #4,d7
- bsr cia_wait
- rts
- shortwait
- nop
- nop
- nop
- nop
- rts
-
- initialize_drive
-
- btst #$4,$1001(a1)
- beq.s gottrack0
- bsr.s stepout
- bra.s initialize_drive
-
- gottrack0 moveq #0,d7
- move.b use_drive(a2),d7
- clr.b tracksides(a2,d7.w)
- move.w #20,d7
- bsr cia_wait
- rts
-
- Identify_disk
-
- movem.l a5/a6/d0-d1/d4-d7,-(a7)
- move.w #$370,d0
- bsr get_block
- moveq #0,d6
- move.b use_drive(a2),d6
- lea disk_names(a2),a5
- lsl.w #5,d6
- add.w d6,a5
- tst.b error(a2)
- beq.s dirblk_ok
- moveq #$1f,d7 ;disk bad - clear name
- clr_name2 clr.b (a5)+
- dbf d7,clr_name2
- bra identifd
-
- dirblk_ok move.l #block_buffer+$1b0,a6 ;copy name to store
- moveq #0,d7
- move.b (a6),d7
- copy_name move.b (a6)+,(a5)+
- dbf d7,copy_name
-
- Identifd move.b #$ff,track_in(a2)
- movem.l (a7)+,a5/a6/d0-d1/d4-d7
- rts
-
- test_step moveq #0,d7
- move.b use_drive(a2),d7
- btst #1,tracksides(a2,d7.w)
- beq.s chkstp_in
- bsr stepout
- bra stepdone
- chkstp_in bsr stepin
- stepdone rts
-
-
- wait1msec moveq #1,d7
-
- cia_wait move.b #$08,$f00(a1) ;set one shot / stop timer
- move.b #$cc,$600(a1) ;set timer lo
- move.b #$02,$700(a1) ;set timer hi (starts counter)
- ciawlp2 btst #0,$f00(a1) ;wait for ciab timer b to timeout
- bne.s ciawlp2
- subq.w #1,d7
- bne.s cia_wait ;d1 = milliseconds to wait.
- rts
-
- *******************************************************************************
-
- attempts equ $0
- error equ $2
- start_motor equ $3
- tracksides equ $4
- track_in equ $8
- use_drive equ $9
- drives_avail equ $a
- mode equ $b
- load_address equ $c
- disk_names equ $10
-
- variables dcb.l $24,$0
-
- direct_names
-
- dc.b "df0:df1:df2:df3:"
-
- block_buffer
-
- dcb.w $100,$0000
-
-
- section chipstuff,data_c
-
- mfmbuffer dcb.w $1910,$0000
-
- *******************************************************************************
-
-